# -*- coding: utf-8 -*-

# 引入os模块，用来解析文件路径
import os

# 引入QgsRasterLayer和QgsVectorLayer类，用来加载栅格和矢量图层
from qgis.core import (
    Qgis,
    QgsRasterLayer,
    QgsVectorLayer,
    QgsSymbol,
    QgsSingleSymbolRenderer,
    QgsDataSourceUri,
    QgsProject,
    QgsMapSettings,
    QgsMapRendererSequentialJob
)

# 引入QtGui模块
from PyQt5.QtGui import (
    QImage, 
    QPixmap, 
    QIcon
)

# 引入QtCore模块
from PyQt5.QtCore import (
    QSize
)

from urllib.parse import urlencode,urlparse, parse_qs,urlunparse

from src.QgsExtrasTools_hli.UtilsTool.QESymbolTool import SymbolTools # 引入符号工具


class LayerTools:
    """
    图层工具类
    """
    # 加载栅格图层
    # staticmethod表示该方法不需要创建对象就可以直接调用
    # staticmethod将load_raster_layer方法设置为静态方法,可以直接通过类名调用

    @staticmethod
    def load_raster_layer(path_to_raster: str):
        """
        加载栅格图层
        param: path_to_raster 栅格文件路径
        return: QgsRasterLayer对象
        """
        # 获取文件路径
        # 通过文件路径获取栅格图层对象，并判断是否加载成功
        # os.path.basename(path_to_raster)[:-4]表示获取文件名，并去掉文件名的后缀
        raster_layer = QgsRasterLayer(path_to_raster, os.path.basename(path_to_raster)[:-4])
        if not raster_layer.isValid():
            print(f"Failed to load raster layer: {path_to_raster}")
            return None
        
        # 设置图层的CRS
        raster_layer.setCrs(QgsProject.instance().crs())

        return raster_layer
    
    # 加载矢量图层
    # staticmethod表示该方法不需要创建对象就可以直接调用
    # staticmethod将load_vector_layer方法设置为静态方法,可以直接通过类名调用
    # os.path.basename(path_to_raster)[:-4]表示获取文件名，并去掉文件名的后缀
    @staticmethod
    def load_vector_layer(path_to_vector: str):
        """
        加载矢量图层
        param: path_to_vector 矢量文件路径
        return: QgsVectorLayer对象
        """
        # 获取文件路径
        # 通过文件路径获取矢量图层对象，并判断是否加载成功
        vector_layer = QgsVectorLayer(path_to_vector, os.path.basename(path_to_vector)[:-4], "ogr")

        # 获取图层的WKB类型
        wkb_type = vector_layer.wkbType()

        # 判断当前加载的矢量是否有效
        if not vector_layer.isValid():
            print(f"Failed to load vector layer: {path_to_vector}")
            return None

        # 设置图层的CRS
        vector_layer.setCrs(QgsProject.instance().crs())

        return vector_layer
    
    @staticmethod
    def get_layer_icon(layer):
        """
        获取图层的图标
        param: layer 图层对象
        return: 图层的图标对象
        """
        img = QImage()
       
        if isinstance(layer,QgsVectorLayer):
            v_layer:QgsVectorLayer = layer
            renderer = v_layer.renderer()
            if isinstance(renderer,QgsSingleSymbolRenderer):
                single_renderer:QgsSingleSymbolRenderer = renderer
                symbol = single_renderer.symbol()
                img = symbol.asImage(QSize(16,16))
        elif isinstance(layer,QgsRasterLayer):
            map_settings = QgsMapSettings()
            map_settings.setLayers([layer])
            map_settings.setOutputSize(QSize(16,16))
            map_settings.setExtent(layer.extent())
            map_settings.setFlag(Qgis.MapSettingsFlag.Antialiasing,True)

            job = QgsMapRendererSequentialJob(map_settings)

            job.finished.connect(lambda: img.swap(job.renderedImage()))

            job.start()
            job.waitForFinished()
            
        pixmap = QPixmap.fromImage(img)
        return QIcon(pixmap)

    @staticmethod
    def set_vectorlayer_symbol(layer:QgsVectorLayer,symbol:QgsSymbol):
        """
        设置矢量图层的符号表
        param: layer 矢量图层对象
        param: symbol  符号对象
        """
        renderer = layer.renderer()
        if isinstance(renderer, QgsSingleSymbolRenderer):
            # 如果是单符号渲染器，则创建新的单符号渲染器
            SymbolTools.set_symbol(renderer,symbol)
            layer.setRenderer(renderer)
        layer.triggerRepaint() # 刷新图层

    @staticmethod
    def get_vectorlayer_symbol(layer:QgsVectorLayer):
        """
        获取矢量图层的符号表
        param: layer 矢量图层对象
        return: 符号对象
        """
        renderer = layer.renderer()
        if isinstance(renderer, QgsSingleSymbolRenderer):
            return SymbolTools.get_symbol(renderer)

    
    # 加载WMS服务图层
    # staticmethod表示该方法不需要创建对象就可以直接调用
    # staticmethod将load_WNS_layer方法设置为静态方法,可以直接通过类名调用
    @staticmethod
    def load_WMS_layer(layer_name : str,layer_url:str):
        """
        加载WMS服务图层
        param: layer_name 图层名称
        param: layer_url 图层url
        return: QgsRasterLayer对象
        """

        # 将url全部转换为小写
        uri = layer_url.lower()

        # 通过urlparse解析url
        # urlparse返回一个ParseResult对象，该对象包含url的各个部分
        parsed_url = urlparse(uri)
        # 获取url的参数
        params = parse_qs(parsed_url.query)

        # 构建wms服务的uri参数
        quri = QgsDataSourceUri()
        quri.setParam("layers", params["layers"][0])
        quri.setParam("styles", '')
        quri.setParam("format", 'image/png')

        # 判断layer_url中是否有srs或者crs参数
        # 有的话赋值给quri的crs参数,没有的话使用WGS_1984坐标系参数
        if "srs" in params:
            quri.setParam("crs", params["srs"][0])
        elif "crs" in params:
            quri.setParam("crs", params["crs"][0])
        else:
            quri.setParam("crs", 'EPSG:4326')
        quri.setParam("dpiMode", 'all')
        quri.setParam("featureCount", '10')
        quri.setParam("contextualWMSLegend", '0')
        quri.setParam("url", uri)

        # 创建WMS图层对象
        wms_layer = QgsRasterLayer(str(quri.encodedUri(),"utf-8"), params["layers"][0], 'wms')

        # 判断wms图层对象是否创建成功
        # 如果创建失败，则打印失败原因
        if not wms_layer.isValid():
            print(wms_layer.error().message())
        
        # 设置图层的CRS
        wms_layer.setCrs(QgsProject.instance().crs())

        # 设置图层名称
        wms_layer.setName(layer_name)

        return wms_layer
    
    @staticmethod
    def load_WMTS_layer(layer_name : str,layer_url:str):
        """
        加载WMTS服务图层
        param: layer_name 图层名称
        param: layer_url 图层url
        return: QgsRasterLayer对象
        """
        uri = layer_url.lower()
        parsed_url = urlparse(uri)
        params = parse_qs(parsed_url.query)
        
        params = {
            'service': 'WMTS',
            'version': '1.0.0',
            'request': 'GetTile',
            'layer': params["layer"][0],
            'style': 'default',
            'format': 'image/png',
            'tilematrixset': 'EPSG:4326',
            'tilematrix': '{z}',
            'tilerow': '{y}',
            'tilecol': '{x}'
        }
        new_url_tuple = (parsed_url.scheme, parsed_url.netloc, parsed_url.path, '', '', '')
        # 组合成新的URL字符串
        url_without_query = urlunparse(new_url_tuple)
        new_uri = '{}?{}'.format(url_without_query, urlencode(params))
        print(new_uri)
        quri = QgsDataSourceUri()
        quri.setParam("type", "xyz")
        quri.setParam("layer", params["layer"][0])
        quri.setParam("styles", '')
        quri.setParam("format", 'image/png')
        quri.setParam("crs", 'EPSG:4326')
        quri.setParam("dpiMode", 'all')
        quri.setParam("featureCount", '10')
        quri.setParam("contextualWMSLegend", '0')
        quri.setParam("url", new_uri)
        
        wmts_layer = QgsRasterLayer(str(quri.encodedUri(),'utf-8'), params["layer"][0], 'wms')
    
        if not wmts_layer.isValid():
            print(wmts_layer.error().message())
       
        # 设置图层的CRS
        wmts_layer.setCrs(QgsProject.instance().crs())

        # 设置图层名称
        wmts_layer.setName(layer_name)

        return wmts_layer